# middleware.py
import time
import logging

from django.http import JsonResponse
from tools.myjwt import mjwt
from tools.myredis import mredis
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin

logger = logging.getLogger(__name__)





class AuthMiddleware(MiddlewareMixin):
    """
    验证请求中的Token和权限的中间件
    """

    def process_request(self, request):
        # 白名单路径，不需要验证
        WHITELIST = [
            '/',  # 根路径
            '/favicon.ico',  # 网站图标
            '/api/login/',  # 登录接口
            '/api/sendsms/',  # 发送短信接口
            '/api/imagecode/',  # 图片验证码接口
            '/api/auth/qq/login/',  # QQ登录接口
            '/api/auth/qq/callback/',  # QQ登录回调接口
            '/api/auth/bind-phone/',  # 绑定手机号接口
            '/api/gitee_auth/',  # Gitee授权接口
            '/api/gitee_callback/',  # Gitee回调接口
            '/api/wechat-login/',  # 微信登录接口
            '/api/wechat-callback/',  # 微信回调接口
            '/api/wechat-login/',  # 微信登录接口
            '/api/wechat-callback/',  # 微信登录回调接口
            '/admin/',  # Django管理后台
            '/api/admin/',  # API管理接口
            '/api/refresh-token/',  # 刷新token接口
            '/api/oauth/url/',  # 工厂模式OAuth URL生成接口
            '/api/oauth/callback/',  # 工厂模式OAuth回调接口
            '/user/dingdingCallback/',  # 钉钉登录回调接口
            '/verify/qutoken/',   # 七牛云token
            '/verify/idcard/',   # 百度身份验证接口
            '/verify/submit/',   # 验证信息写入表中+修改认证状态
            '/verify/status',    # 获取认证状态
            '/report/general_agent',    # 生成ai训练计划
            '/report/user-workout-plan',    # 获取用户最近一次AI训练计划
            '/verify/checkidcardmes',   # 获取定时任务中的redis身份数据
            '/user/qiniu-token/',
            '/user/qiniu-download-token/',
            '/api/userinfo/',  # 获取用户信息接口
            '/api/diet/generate-plan',
            '/api/diet/user-profile',
            
            # diet相关接口 - 这些接口需要认证，不应该在白名单中
            # 但是为了确保认证正常工作，我们需要确保它们能正确通过JWT验证
        ]

        path = request.path

        # 检查请求路径是否在白名单中
        # 支持带尾部斜杠和不带尾部斜杠的路径
        whitelist_paths = [w.rstrip('/') for w in WHITELIST]
        current_path = path.rstrip('/')
        
        # 调试信息
        print(f"当前请求路径: {current_path}")
        print(f"白名单路径: {whitelist_paths}")
        
        # 检查是否在白名单中
        if current_path in whitelist_paths:
            print(f"✅ 路径 {current_path} 在白名单中，尝试获取用户信息但不强制要求")
            
            # 对于白名单路径，尝试解析token但不强制要求
            auth_header = request.headers.get("Authorization")
            if auth_header:
                print(f"🔍 白名单路径检测到Authorization头，尝试解析token")
                try:
                    # 处理Bearer token格式
                    if auth_header.startswith('Bearer '):
                        token = auth_header[7:]  # 移除 'Bearer ' 前缀
                    else:
                        token = auth_header  # 如果没有Bearer前缀，直接使用

                    # 解析JWT token
                    print(f"🔍 开始解析token: {token[:20]}...")
                    payload = mjwt.decode(token)
                    if payload and not mjwt.is_expired(payload):
                        # 检查token是否被退出
                        value = mredis.get(token)
                        if not value:
                            # 将用户信息存储到request中，供后续视图使用
                            request.user_info = payload
                            print(f"✅ 白名单路径成功设置用户信息: {payload}")
                        else:
                            print(f"⚠️ 白名单路径token已退出，跳过用户信息设置")
                    else:
                        print(f"⚠️ 白名单路径token无效或已过期，跳过用户信息设置")
                except Exception as e:
                    print(f"⚠️ 白名单路径token解析失败: {e}，跳过用户信息设置")
            else:
                print(f"ℹ️ 白名单路径未检测到Authorization头，将使用匿名模式")
            
            return None  # 白名单路径，直接通过
        else:
            print(f"❌ 路径 {current_path} 不在白名单中，需要认证")
            
        # 特殊处理：检查是否是diet相关路径
        if current_path.startswith('/api/diet'):
            print(f"🔍 检测到diet路径: {current_path}，需要JWT认证")

        # 不在白名单中，需要验证token
        auth_header = request.headers.get("Authorization")   # 从请求头中获取
        
        print(f"🔍 认证调试 - 路径: {current_path}")
        print(f"🔍 认证调试 - Authorization头: {auth_header}")

        if not auth_header:
            print(f"❌ 缺少Authorization头")
            return JsonResponse({
                "code": 401,
                "message": "未登录，请先登录",
                "success": False
            }, status=401)

        # 处理Bearer token格式
        if auth_header.startswith('Bearer '):
            token = auth_header[7:]  # 移除 'Bearer ' 前缀
        else:
            token = auth_header  # 如果没有Bearer前缀，直接使用

        # 解析JWT token
        print(f"🔍 开始解析token: {token[:20]}...")
        try:
            payload = mjwt.decode(token)
            print(f"🔍 token解析结果: {payload}")
            if not payload:
                print(f"❌ token解析失败")
                return JsonResponse({
                    "code": 401,
                    "message": "token无效，已过期",
                    "success": False
                }, status=401)

            # 检查用户是否退出-->token存储在redis中，查询到了就是退出了
            # 防止有人监听到token在过期时间内还能使用
            value = mredis.get(token)
            if value:
                return JsonResponse({
                    "code": 401,
                    "message": "用户已退出，请重新登录",
                    "success": False
                })
            # # 多端验证登陆
            # key = "login" + str(payload["user_id"])
            # tokenvalue = mredis.get(key)
            # if token != tokenvalue:
            #     return JsonResponse({
            #         "code": 401,
            #         "message": "已在其他设备登录"
            #     })

            # 检查token是否过期
            if mjwt.is_expired(payload):
                return JsonResponse({
                    "code": 401,
                    "message": "token已过期，请重新登录",
                    "success": False
                }, status=401)

            # 检查token是否被退出（黑名单检查）
            token_blacklist_key = f"token_blacklist:{token}"
            if mredis.exists(token_blacklist_key):
                return JsonResponse({
                    "code": 401,
                    "message": "token已退出，请重新登录",
                    "success": False
                }, status=401)

            # 将用户信息存储到request中，供后续视图使用
            request.user_info = payload

            # 设置Django User对象给request.user
            from django.contrib.auth import get_user_model
            User = get_user_model()
            try:
                user = User.objects.get(id=payload['user_id'])
                request.user = user
            except User.DoesNotExist:
                return JsonResponse({
                    "code": 401,
                    "message": "用户不存在",
                    "success": False
                }, status=401)

            return None  # 验证通过，继续处理请求

        except Exception as e:
            logger.error(f"Token验证异常: {e}")
            return JsonResponse({
                "code": 401,
                "message": "token验证失败",
                "success": False
            }, status=401)

    def process_response(self, request, response):
        """处理响应，可以在这里添加一些通用的响应头"""
        return response
